Skip to content

Robot 210426#2302

Merged
simo6529 merged 3 commits intomainfrom
robot-210426
Apr 22, 2026
Merged

Robot 210426#2302
simo6529 merged 3 commits intomainfrom
robot-210426

Conversation

@simo6529
Copy link
Copy Markdown
Collaborator

@simo6529 simo6529 commented Apr 22, 2026

Summary by CodeRabbit

Release Notes

  • New Features

    • AI profiles now display a visual robot emoji indicator (🤖) with accessible "AI profile" labeling throughout the platform, including user pages and content drops
    • Added profile wave endpoint support
  • Tests

    • Added comprehensive test coverage for AI profile indicators and accessibility features across profile display components

Signed-off-by: Simo <simo@6529.io>
Signed-off-by: Simo <simo@6529.io>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 22, 2026

📝 Walkthrough

Walkthrough

This PR introduces AI profile classification rendering by adding a new ProfileNameWithAiMarker component that conditionally displays a 🤖 emoji for AI-classified profiles. It integrates this component into multiple UI layers (user page headers, wave drops), extends API schemas with classification and sub_classification fields, and updates profile builders and helpers to propagate these fields throughout the codebase.

Changes

Cohort / File(s) Summary
ProfileNameWithAiMarker Component
components/common/profile/ProfileNameWithAiMarker.tsx, __tests__/components/common/profile/ProfileNameWithAiMarker.test.tsx
New component that conditionally renders a 🤖 emoji and accessible "AI profile" text when classification === ApiProfileClassification.Ai; includes tests for AI and non-AI profiles.
User Page Header Integration
components/user/user-page-header/name/UserPageHeaderName.tsx, __tests__/components/user/user-page-header/name/UserPageHeaderName.test.tsx
Wrapped profile display name with ProfileNameWithAiMarker to show AI marker; updated tests to verify emoji and accessible text rendering for AI profiles.
Wave Drop Author Components
components/waves/drop/SingleWaveDropAuthor.tsx, components/waves/drops/DropMinimalIdentityRow.tsx, components/waves/drops/WaveDropHeader.tsx, __tests__/components/waves/drop/SingleWaveDropAuthor.test.tsx, __tests__/components/waves/drops/DropMinimalIdentityRow.test.tsx, __tests__/components/waves/drops/WaveDropHeader.test.tsx
Integrated ProfileNameWithAiMarker into author name rendering; centralized authorIdentity computation; added tests verifying AI emoji display and accessibility attributes.
Drop Author Badges & Utilities
components/waves/drops/DropAuthorBadges.tsx, components/manifold-minting/ManifoldMinting.tsx
Extended DropAuthorBadgesProfile interface to require classification and sub_classification fields; updated data mapper to include these fields in ApiProfileMin.
Profile Builders & Helpers
components/waves/drops/reaction-utils.ts, components/waves/memes/submission/utils/buildPreviewDrop.ts, components/waves/utils/getOptimisticDrop.ts, components/waves/specs/groups/group/edit/WaveGroupChangeDialog.tsx, helpers/ProfileHelpers.ts
Added classification and sub_classification field propagation across profile-building utilities with appropriate defaults (Pseudonym classification, null sub-classification).
OpenAPI Schema Updates
openapi.yaml
Added new GET /profiles/{identity}/wave endpoint returning ApiProfileWave; extended ApiProfileMin to require classification and sub_classification; added new schemas for ApiPaymentDetails and ApiProfileWave; extended ApiSetProfileWaveRequest with optional profile_curation_id.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • ragnep
  • GelatoGenesis
  • prxt6529

Poem

🐰 A marker bold for AI souls takes flight,
With robot emoji shining bright,
Through every drop and profile deep,
Classification secrets keep!
From schema flows to UI's art,
The AI badge plays its part! 🤖

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'Robot 210426' is vague and generic, using non-descriptive terms that do not convey meaningful information about the substantial feature additions throughout the changeset. Revise the title to clearly describe the main change, such as 'Add AI profile indicator marker component and integrate across components' to reflect the primary feature addition.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch robot-210426

Warning

Review ran into problems

🔥 Problems

Timed out fetching pipeline failures after 30000ms


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (4)
components/waves/utils/getOptimisticDrop.ts (1)

93-94: Consider a defensive fallback for classification consistent with buildPreviewDrop.

buildPreviewDrop falls back to ApiProfileClassification.Pseudonym when missing, but here the value is passed through directly. If any stale/cached connectedProfile lacks classification at runtime (e.g., during rollout), the optimistic drop author would carry undefined, which violates the ApiProfileMin contract and could break downstream consumers like ProfileNameWithAiMarker. Mirroring the preview builder's fallback would be safer.

♻️ Suggested change
-      classification: connectedProfile.classification,
-      sub_classification: connectedProfile.sub_classification,
+      classification:
+        connectedProfile.classification ?? ApiProfileClassification.Pseudonym,
+      sub_classification: connectedProfile.sub_classification ?? null,

(Requires importing ApiProfileClassification.)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/waves/utils/getOptimisticDrop.ts` around lines 93 - 94,
getOptimisticDrop currently passes connectedProfile.classification through
directly which can be undefined; update getOptimisticDrop to mirror
buildPreviewDrop by importing ApiProfileClassification and defaulting
classification to ApiProfileClassification.Pseudonym when
connectedProfile.classification is falsy, so the optimistic drop (and its
ApiProfileMin shape used by components like ProfileNameWithAiMarker) always has
a valid classification value.
components/common/profile/ProfileNameWithAiMarker.tsx (1)

15-24: Optional: consider merging className with defaults instead of replacing.

Currently, any caller passing className loses DEFAULT_CLASS_NAME (flex/gap), silently breaking marker layout. Either document this explicitly, or compose the classes (e.g., via clsx) so consumers can augment rather than replace.

♻️ Suggested refactor
-export default function ProfileNameWithAiMarker({
-  classification,
-  children,
-  className = DEFAULT_CLASS_NAME,
-  markerClassName,
-}: ProfileNameWithAiMarkerProps) {
+export default function ProfileNameWithAiMarker({
+  classification,
+  children,
+  className,
+  markerClassName,
+}: ProfileNameWithAiMarkerProps) {
   const isAiProfile = classification === ApiProfileClassification.Ai;
 
   return (
-    <span className={className}>
+    <span className={className ? `${DEFAULT_CLASS_NAME} ${className}` : DEFAULT_CLASS_NAME}>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@components/common/profile/ProfileNameWithAiMarker.tsx` around lines 15 - 24,
ProfileNameWithAiMarker currently replaces DEFAULT_CLASS_NAME when a caller
supplies className which breaks layout; update the component to merge
DEFAULT_CLASS_NAME with the incoming className (e.g., via clsx or a simple
`${DEFAULT_CLASS_NAME} ${className}` composition) when building the span's
className, and similarly compose markerClassName with its default if present;
modify the return span in ProfileNameWithAiMarker to use the composed class
strings so callers can augment rather than replace the defaults (leave
ApiProfileClassification.Ai, children and other logic unchanged).
__tests__/components/waves/drops/DropMinimalIdentityRow.test.tsx (1)

65-74: Weak negative assertion for the robot emoji.

not.toHaveTextContent("🤖") on the tooltip wrapper only checks the mocked tooltip subtree. A stronger, more intent-revealing assertion would be expect(screen.queryByText("🤖")).not.toBeInTheDocument();, matching the pattern used in ProfileNameWithAiMarker.test.tsx.

🔧 Suggested change
-    expect(screen.getByRole("link", { name: "human" })).toBeInTheDocument();
-    expect(screen.getByTestId("tooltip-wrapper")).not.toHaveTextContent("🤖");
+    expect(screen.getByRole("link", { name: "human" })).toBeInTheDocument();
+    expect(screen.queryByText("🤖")).not.toBeInTheDocument();
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@__tests__/components/waves/drops/DropMinimalIdentityRow.test.tsx` around
lines 65 - 74, Replace the weak negative assertion on the tooltip subtree with a
global DOM absence check: in the test that renders DropMinimalIdentityRow (the
case using createDrop("human", "0xabc", ApiProfileClassification.Pseudonym)),
remove expect(screen.getByTestId("tooltip-wrapper")).not.toHaveTextContent("🤖")
and instead assert expect(screen.queryByText("🤖")).not.toBeInTheDocument(); so
the test verifies the robot emoji is not present anywhere in the rendered
output.
__tests__/components/waves/drops/WaveDropHeader.test.tsx (1)

95-108: Same weak negative assertion as in DropMinimalIdentityRow.test.tsx.

Prefer expect(screen.queryByText("🤖")).not.toBeInTheDocument(); over not.toHaveTextContent("🤖") scoped to the tooltip wrapper, for consistency with ProfileNameWithAiMarker.test.tsx and a stronger assertion.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@__tests__/components/waves/drops/WaveDropHeader.test.tsx` around lines 95 -
108, Replace the weak negative assertion in the "does not render a robot emoji
for non-AI profiles" test in WaveDropHeader.test.tsx: instead of asserting the
tooltip wrapper does not have text content "🤖" via
getByTestId("tooltip-wrapper"), use a global query for the emoji and assert it
is not present (expect(screen.queryByText("🤖")).not.toBeInTheDocument()),
matching the stronger pattern used in ProfileNameWithAiMarker.test.tsx; update
the assertion in the test for WaveDropHeader accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@components/user/user-page-header/name/UserPageHeaderName.tsx`:
- Around line 57-64: The inline <span> inside ProfileNameWithAiMarker can
misalign with the smaller marker; restore the original block-level semantics or
enforce vertical centering: replace the inner <span> with the previous <p> that
carried the typography (ensuring no default margins) or add alignment utility
classes on ProfileNameWithAiMarker (e.g., make it an inline-flex/flex container
with items-center) so the displayName text and the 🤖 marker vertically align
across breakpoints; update the JSX where ProfileNameWithAiMarker is used and
adjust classes (tw-*) accordingly.

In `@components/waves/drops/DropAuthorBadges.tsx`:
- Around line 42-43: The change made `classification` and `sub_classification`
required breaks callers (e.g., the test's baseProfile) and toApiProfileMin
passes them through without fallbacks; revert this by making those fields
optional on the ApiProfile type (or change DropAuthorBadges props to accept
optional fields) and update toApiProfileMin to provide safe defaults (e.g.,
profile.classification ?? <default> and profile.sub_classification ?? null),
and/or update the test fixture baseProfile in DropAuthorBadges.test.tsx to
include valid values for classification and sub_classification so all callers
compile under strict TypeScript.

In `@openapi.yaml`:
- Around line 10500-10512: ApiPaymentDetails currently forces
designated_payee_name to be a non-null string; update the ApiPaymentDetails
schema so designated_payee_name can be null when has_designated_payee is false
by making the designated_payee_name property nullable (OpenAPI 3.0: add
nullable: true) or permitting ["string","null"] (OpenAPI 3.1), keeping the
property name as designated_payee_name and leaving has_designated_payee as-is;
ensure schema validation accepts null payloads for designated_payee_name.

---

Nitpick comments:
In `@__tests__/components/waves/drops/DropMinimalIdentityRow.test.tsx`:
- Around line 65-74: Replace the weak negative assertion on the tooltip subtree
with a global DOM absence check: in the test that renders DropMinimalIdentityRow
(the case using createDrop("human", "0xabc",
ApiProfileClassification.Pseudonym)), remove
expect(screen.getByTestId("tooltip-wrapper")).not.toHaveTextContent("🤖") and
instead assert expect(screen.queryByText("🤖")).not.toBeInTheDocument(); so the
test verifies the robot emoji is not present anywhere in the rendered output.

In `@__tests__/components/waves/drops/WaveDropHeader.test.tsx`:
- Around line 95-108: Replace the weak negative assertion in the "does not
render a robot emoji for non-AI profiles" test in WaveDropHeader.test.tsx:
instead of asserting the tooltip wrapper does not have text content "🤖" via
getByTestId("tooltip-wrapper"), use a global query for the emoji and assert it
is not present (expect(screen.queryByText("🤖")).not.toBeInTheDocument()),
matching the stronger pattern used in ProfileNameWithAiMarker.test.tsx; update
the assertion in the test for WaveDropHeader accordingly.

In `@components/common/profile/ProfileNameWithAiMarker.tsx`:
- Around line 15-24: ProfileNameWithAiMarker currently replaces
DEFAULT_CLASS_NAME when a caller supplies className which breaks layout; update
the component to merge DEFAULT_CLASS_NAME with the incoming className (e.g., via
clsx or a simple `${DEFAULT_CLASS_NAME} ${className}` composition) when building
the span's className, and similarly compose markerClassName with its default if
present; modify the return span in ProfileNameWithAiMarker to use the composed
class strings so callers can augment rather than replace the defaults (leave
ApiProfileClassification.Ai, children and other logic unchanged).

In `@components/waves/utils/getOptimisticDrop.ts`:
- Around line 93-94: getOptimisticDrop currently passes
connectedProfile.classification through directly which can be undefined; update
getOptimisticDrop to mirror buildPreviewDrop by importing
ApiProfileClassification and defaulting classification to
ApiProfileClassification.Pseudonym when connectedProfile.classification is
falsy, so the optimistic drop (and its ApiProfileMin shape used by components
like ProfileNameWithAiMarker) always has a valid classification value.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 9f6081c4-f817-4cc4-935e-77a7e755cb02

📥 Commits

Reviewing files that changed from the base of the PR and between 23d142d and 2a1adbc.

⛔ Files ignored due to path filters (7)
  • generated/models/ApiDropResolvedIdentityProfile.ts is excluded by !**/generated/**
  • generated/models/ApiMemesMintStat.ts is excluded by !**/generated/**
  • generated/models/ApiPaymentDetails.ts is excluded by !**/generated/**
  • generated/models/ApiProfileMin.ts is excluded by !**/generated/**
  • generated/models/ApiProfileWave.ts is excluded by !**/generated/**
  • generated/models/ApiSetProfileWaveRequest.ts is excluded by !**/generated/**
  • generated/models/ObjectSerializer.ts is excluded by !**/generated/**
📒 Files selected for processing (18)
  • __tests__/components/common/profile/ProfileNameWithAiMarker.test.tsx
  • __tests__/components/user/user-page-header/name/UserPageHeaderName.test.tsx
  • __tests__/components/waves/drop/SingleWaveDropAuthor.test.tsx
  • __tests__/components/waves/drops/DropMinimalIdentityRow.test.tsx
  • __tests__/components/waves/drops/WaveDropHeader.test.tsx
  • components/common/profile/ProfileNameWithAiMarker.tsx
  • components/manifold-minting/ManifoldMinting.tsx
  • components/user/user-page-header/name/UserPageHeaderName.tsx
  • components/waves/drop/SingleWaveDropAuthor.tsx
  • components/waves/drops/DropAuthorBadges.tsx
  • components/waves/drops/DropMinimalIdentityRow.tsx
  • components/waves/drops/WaveDropHeader.tsx
  • components/waves/drops/reaction-utils.ts
  • components/waves/memes/submission/utils/buildPreviewDrop.ts
  • components/waves/specs/groups/group/edit/WaveGroupChangeDialog.tsx
  • components/waves/utils/getOptimisticDrop.ts
  • helpers/ProfileHelpers.ts
  • openapi.yaml

Comment thread components/user/user-page-header/name/UserPageHeaderName.tsx
Comment thread components/waves/drops/DropAuthorBadges.tsx
Comment thread openapi.yaml
@sonarqubecloud
Copy link
Copy Markdown

@simo6529 simo6529 merged commit 70f4565 into main Apr 22, 2026
8 checks passed
@simo6529 simo6529 deleted the robot-210426 branch April 22, 2026 06:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants